Thursday, May 5, 2022

Arduino Based Smart Weather Station

 Arduino Based Smart Weather Station


COMPONENT'S FOR THIS PROJECT'S

· NODE-MCU (ESP-8266)

· SERIAL USB CABEL

· TEMPERATURE SENSOR (DHT-11) 

· OLED DISPLAY

· BREAD-BOARD

· JUMPER WIRES

· BATTERY (optional) you can also use by usb cabel power supply

SOFTWARE & APPLICATION

· ARDUINO IDE

https://www.arduino.cc/en/software


CIRCUIT DIAGRAM



ARDUINO CODE'S


#include <Arduino.h>

#include <ESPWiFi.h>

#include <ESPHTTPClient.h>

#include <JsonListener.h> 

#include <time.h>                       // time() ctime()

#include <sys/time.h>                   // struct timeval

#include <coredecls.h>                  // settimeofday_cb()


#include "SSD1306Wire.h"

#include "OLEDDisplayUi.h"

#include "Wire.h"

#include "OpenWeatherMapCurrent.h"

#include "OpenWeatherMapForecast.h"

#include "WeatherStationFonts.h"

#include "WeatherStationImages.h"

#include "DHT.h"


const char* WIFI_SSID = "Gaurav Sharma";

const char* WIFI_PWD = "access@denied";


#define TZ              5       // (utc+) TZ in hours

#define DST_MN          30      // use 60mn for summer time in some countries


// Setup

const int UPDATE_INTERVAL_SECS = 10 * 60; // Update every 30 minutes


// Display Settings

const int I2C_DISPLAY_ADDRESS = 0x3C;

#if defined(ESP8266)

const int SDA_PIN = D2;

const int SDC_PIN = D1;

#else

const int SDA_PIN = 19; //D3;

const int SDC_PIN = 20; //D4;

#endif


String OPEN_WEATHER_MAP_APP_ID = "471a17ddf68029674538e9e1663f7262";

String OPEN_WEATHER_MAP_LOCATION_ID = "1271942";


String OPEN_WEATHER_MAP_LANGUAGE = "en";

const uint8_t MAX_FORECASTS = 4;


const boolean IS_METRIC = true;


// Adjust according to your language

const String WDAY_NAMES[] = {"SUN", "MON", "TUE", "WED", "THU", "FRI", "SAT"};

const String MONTH_NAMES[] = {"JAN", "FEB", "MAR", "APR", "MAY", "JUN", "JUL", "AUG", "SEP", "OCT", "NOV", "DEC"};


/***************************

 * End Settings

 **************************/

 SSD1306Wire     display(I2C_DISPLAY_ADDRESS, SDA_PIN, SDC_PIN);

 OLEDDisplayUi   ui( &display );


OpenWeatherMapCurrentData currentWeather;

OpenWeatherMapCurrent currentWeatherClient;


OpenWeatherMapForecastData forecasts[MAX_FORECASTS];

OpenWeatherMapForecast forecastClient;


#define TZ_MN           ((TZ)*60)

#define TZ_SEC          ((TZ)*3600)

#define DST_SEC         ((DST_MN)*60)

time_t now;


// flag changed in the ticker function every 10 minutes

bool readyForWeatherUpdate = false;


String lastUpdate = "--";


long timeSinceLastWUpdate = 0;


//declaring prototypes

void drawProgress(OLEDDisplay *display, int percentage, String label);

void updateData(OLEDDisplay *display);

void drawDateTime(OLEDDisplay *display, OLEDDisplayUiState* state, int16_t x, int16_t y);

void drawTemp(OLEDDisplay *display, OLEDDisplayUiState* state, int16_t x, int16_t y);

void drawHum(OLEDDisplay *display, OLEDDisplayUiState* state, int16_t x, int16_t y);

void drawCurrentWeather(OLEDDisplay *display, OLEDDisplayUiState* state, int16_t x, int16_t y);

void drawForecast(OLEDDisplay *display, OLEDDisplayUiState* state, int16_t x, int16_t y);

void drawForecastDetails(OLEDDisplay *display, int x, int y, int dayIndex);

void drawHeaderOverlay(OLEDDisplay *display, OLEDDisplayUiState* state);

void setReadyForWeatherUpdate();


FrameCallback frames[] = { drawDateTime, drawCurrentWeather, drawForecast, drawTemp, drawHum };

int numberOfFrames = 5;


OverlayCallback overlays[] = { drawHeaderOverlay };

int numberOfOverlays = 1;


DHT dht = DHT(D3, DHT11, 6);


void setup() {

  Serial.begin(115200);

  Serial.println();

  Serial.println();


  // initialize dispaly

  display.init();

  display.clear();

  display.display();


  display.setFont(ArialMT_Plain_10);

  display.setTextAlignment(TEXT_ALIGN_CENTER);

  display.setContrast(255);


  dht.begin();

  WiFi.begin(WIFI_SSID, WIFI_PWD);


  int counter = 0;

  while (WiFi.status() != WL_CONNECTED) {

    delay(500);

    Serial.print(".");

    display.clear();

    display.drawString(64, 10, "Connecting to WiFi");

    display.drawXbm(46, 30, 8, 8, counter % 3 == 0 ? activeSymbole : inactiveSymbole);

    display.drawXbm(60, 30, 8, 8, counter % 3 == 1 ? activeSymbole : inactiveSymbole);

    display.drawXbm(74, 30, 8, 8, counter % 3 == 2 ? activeSymbole : inactiveSymbole);

    display.display();


    counter++;

  }


  // Get time from network time service

  configTime(TZ_SEC, DST_SEC, "pool.ntp.org");


  ui.setTargetFPS(30);


  ui.setActiveSymbol(activeSymbole);

  ui.setInactiveSymbol(inactiveSymbole);


  // You can change this to

  // TOP, LEFT, BOTTOM, RIGHT

  ui.setIndicatorPosition(BOTTOM);


  // Defines where the first frame is located in the bar.

  ui.setIndicatorDirection(LEFT_RIGHT);


  // You can change the transition that is used

  // SLIDE_LEFT, SLIDE_RIGHT, SLIDE_TOP, SLIDE_DOWN

  ui.setFrameAnimation(SLIDE_LEFT);


  ui.setFrames(frames, numberOfFrames);


  ui.setOverlays(overlays, numberOfOverlays);


  // Inital UI takes care of initalising the display too.

  ui.init();


  Serial.println("");


  updateData(&display);

  

  display.clear();

  display.drawXbm(26,0,logo1_width,logo1_height,logo1_bits);

  display.display();

  delay(3000);

  

  display.clear();

  display.setTextAlignment(TEXT_ALIGN_LEFT);

  display.setFont(ArialMT_Plain_10);

  display.drawString(0,0,"LOADING");

  display.display();  

  delay(2000);

  display.drawString(0,10,"TIME AND DATE");

  display.display();  

  delay(2000);

  display.drawString(0,20,"TEMPERATURE");

  display.display();  

  delay(2000);

  display.drawString(0,30,"HUMIDITY");

  display.display();  

  delay(2000);

  display.drawString(0,40,"FORECAST");

  display.display();  

  delay(2000);

  display.drawString(0,50,"INITIALIZING GUI");

  display.display();  

  delay(2000);

}


void loop() {

  

  

  if (millis() - timeSinceLastWUpdate > (1000L*UPDATE_INTERVAL_SECS)) {

    setReadyForWeatherUpdate();

    timeSinceLastWUpdate = millis();

  }


  if (readyForWeatherUpdate && ui.getUiState()->frameState == FIXED) {

    updateData(&display);

  }


  int remainingTimeBudget = ui.update();


  if (remainingTimeBudget > 0) {

    // You can do some work here

    // Don't do stuff if you are below your

    // time budget.

    delay(remainingTimeBudget);

  }



}


void drawProgress(OLEDDisplay *display, int percentage, String label) {

  display->clear();

  display->setTextAlignment(TEXT_ALIGN_CENTER);

  display->setFont(ArialMT_Plain_10);

  display->drawString(64, 10, label);

  display->drawProgressBar(2, 28, 124, 10, percentage);

  display->display();

}


void updateData(OLEDDisplay *display) {

  drawProgress(display, 10, "Updating time...");

  drawProgress(display, 30, "Updating weather...");

  currentWeatherClient.setMetric(IS_METRIC);

  currentWeatherClient.setLanguage(OPEN_WEATHER_MAP_LANGUAGE);

  currentWeatherClient.updateCurrentById(&currentWeather, OPEN_WEATHER_MAP_APP_ID, OPEN_WEATHER_MAP_LOCATION_ID);

  drawProgress(display, 50, "Updating forecasts...");

  forecastClient.setMetric(IS_METRIC);

  forecastClient.setLanguage(OPEN_WEATHER_MAP_LANGUAGE);

  uint8_t allowedHours[] = {12};

  forecastClient.setAllowedHours(allowedHours, sizeof(allowedHours));

  forecastClient.updateForecastsById(forecasts, OPEN_WEATHER_MAP_APP_ID, OPEN_WEATHER_MAP_LOCATION_ID, MAX_FORECASTS);


  readyForWeatherUpdate = false;

  drawProgress(display, 100, "Done...");

  delay(1000);

}




void drawDateTime(OLEDDisplay *display, OLEDDisplayUiState* state, int16_t x, int16_t y) {

  now = time(nullptr);

  struct tm* timeInfo;

  timeInfo = localtime(&now);

  char buff[16];



  display->setTextAlignment(TEXT_ALIGN_CENTER);

  display->setFont(ArialMT_Plain_10);

  String date = WDAY_NAMES[timeInfo->tm_wday];


  sprintf_P(buff, PSTR("%s, %02d/%02d/%04d"), WDAY_NAMES[timeInfo->tm_wday].c_str(), timeInfo->tm_mday, timeInfo->tm_mon+1, timeInfo->tm_year + 1900);

  display->drawString(64 + x, 5 + y, String(buff));

  display->setFont(ArialMT_Plain_24);


  sprintf_P(buff, PSTR("%02d:%02d:%02d"), timeInfo->tm_hour, timeInfo->tm_min, timeInfo->tm_sec);

  display->drawString(64 + x, 15 + y, String(buff));

  display->setTextAlignment(TEXT_ALIGN_LEFT);

}


void drawTemp(OLEDDisplay *display, OLEDDisplayUiState* state, int16_t x, int16_t y) {


  float temperature = dht.readTemperature();

  

  display->setTextAlignment(TEXT_ALIGN_CENTER);

  display->setFont(ArialMT_Plain_10);

  

  display->drawString(64 + x, 5 + y, "Room Temperature");

  display->setFont(ArialMT_Plain_24);


  display->drawString(64 + x, 15 + y, String(temperature,1)+("°C"));

  display->setTextAlignment(TEXT_ALIGN_LEFT);

}


void drawHum(OLEDDisplay *display, OLEDDisplayUiState* state, int16_t x, int16_t y) {


  int humidity = dht.readHumidity();

  

  display->setTextAlignment(TEXT_ALIGN_CENTER);

  display->setFont(ArialMT_Plain_10);

  

  display->drawString(64 + x, 5 + y, "Humidity");

  display->setFont(ArialMT_Plain_24);


  display->drawString(64 + x, 15 + y, String(humidity)+(" %"));

  display->setTextAlignment(TEXT_ALIGN_LEFT);

}


void drawCurrentWeather(OLEDDisplay *display, OLEDDisplayUiState* state, int16_t x, int16_t y) {

  display->setFont(ArialMT_Plain_10);

  display->setTextAlignment(TEXT_ALIGN_CENTER);

  display->drawString(64 + x, 38 + y, currentWeather.description);


  display->setFont(ArialMT_Plain_24);

  display->setTextAlignment(TEXT_ALIGN_LEFT);

  String temp = String(currentWeather.temp, 1) + (IS_METRIC ? "°C" : "°F");

  display->drawString(51 + x, 5 + y, temp);


  display->setFont(Meteocons_Plain_36);

  display->setTextAlignment(TEXT_ALIGN_CENTER);

  display->drawString(23  + x, 0 + y, currentWeather.iconMeteoCon);

}

void drawForecast(OLEDDisplay *display, OLEDDisplayUiState* state, int16_t x, int16_t y) {

  drawForecastDetails(display, x, y, 0);

  drawForecastDetails(display, x + 44, y, 1);

  drawForecastDetails(display, x + 88, y, 2);

}


void drawForecastDetails(OLEDDisplay *display, int x, int y, int dayIndex) {

  time_t observationTimestamp = forecasts[dayIndex].observationTime;

  struct tm* timeInfo;

  timeInfo = localtime(&observationTimestamp);

  display->setTextAlignment(TEXT_ALIGN_CENTER);

  display->setFont(ArialMT_Plain_10);

  display->drawString(x + 20, y, WDAY_NAMES[timeInfo->tm_wday]);


  display->setFont(Meteocons_Plain_21);

  display->drawString(x + 20, y + 12, forecasts[dayIndex].iconMeteoCon);

  String temp = String(forecasts[dayIndex].temp, 0) + (IS_METRIC ? "°C" : "°F");

  display->setFont(ArialMT_Plain_10);

  display->drawString(x + 20, y + 34, temp);

  display->setTextAlignment(TEXT_ALIGN_LEFT);

}


void drawHeaderOverlay(OLEDDisplay *display, OLEDDisplayUiState* state) {

  now = time(nullptr);

  struct tm* timeInfo;

  timeInfo = localtime(&now);

  char buff[14];

  sprintf_P(buff, PSTR("%02d:%02d"), timeInfo->tm_hour, timeInfo->tm_min);


  display->setColor(WHITE);

  display->setFont(ArialMT_Plain_10);

  display->setTextAlignment(TEXT_ALIGN_LEFT);

  display->drawString(0, 54, String(buff));

  display->setTextAlignment(TEXT_ALIGN_RIGHT);

  String temp = String(currentWeather.temp, 1) + (IS_METRIC ? "°C" : "°F");

  display->drawString(128, 54, temp);

  display->drawHorizontalLine(0, 52, 128);

}

void setReadyForWeatherUpdate() {

  Serial.println("Setting readyForUpdate to true");

  readyForWeatherUpdate = true;

}

YOUTUBE VIDEO LINK

https://youtu.be/r0Dcoqbspdk

No comments:

Post a Comment

Smart Snapchat Card

  Smart Snapchat Social Media Card Seamless Connections: Adding the Smart Snapchat Card with a Scan or a Simple Hold. Introduction: In the r...